/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Puyo;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 * @author Ming Li
 */
public class PuyoMIDlet extends MIDlet implements CommandListener, Observer {

   private boolean midletPaused = false;
   public static final Command pauseCommand= new Command("Pause", Command.STOP, 1);  
   public static final Command resumeCommand= new Command("Resume", Command.STOP, 1); 
   private PuyoWindow puyoWindow;
   private ScoreScreen scoreScreen;
   private PuyoConfig puyoConfig; 
   //<editor-fold defaultstate="collapsed" desc=" Generated Fields ">//GEN-BEGIN:|fields|0|
   private List listMenu;
   private Form formPlayerName;
   private Spacer spacer;
   private StringItem strItemCurrentPlayerName;
   private TextField txtPlayerName;
   private Form formHelp;
   private StringItem strItemHelp;
   private Command cancelCommand;
   private Command okCommand;
   private Command backCommand;
   private Command exitCommand;
   //</editor-fold>//GEN-END:|fields|0|



   //<editor-fold defaultstate="collapsed" desc=" Generated Methods ">//GEN-BEGIN:|methods|0|
   //</editor-fold>//GEN-END:|methods|0|

   //<editor-fold defaultstate="collapsed" desc=" Generated Method: initialize ">//GEN-BEGIN:|0-initialize|0|0-preInitialize
   /**
    * Initilizes the application.
    * It is called only once when the MIDlet is started. The method is called before the <code>startMIDlet</code> method.
    */
   private void initialize() {//GEN-END:|0-initialize|0|0-preInitialize
        // write pre-initialize user code here
       strItemCurrentPlayerName = new StringItem("Current name: ", "Current Player Name");//GEN-LINE:|0-initialize|1|0-postInitialize
        // write post-initialize user code here     
        getScoreScreen();   
        
        //read current player name from the persistent storage.
        puyoConfig = new PuyoConfig();
        puyoConfig.read();
        strItemCurrentPlayerName.setText(puyoConfig.getCurrentPlayerName());               
   }//GEN-BEGIN:|0-initialize|2|
   //</editor-fold>//GEN-END:|0-initialize|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Method: startMIDlet ">//GEN-BEGIN:|3-startMIDlet|0|3-preAction
   /**
    * Performs an action assigned to the Mobile Device - MIDlet Started point.
    */
   public void startMIDlet() {//GEN-END:|3-startMIDlet|0|3-preAction
        // write pre-action user code here
       switchDisplayable(null, getListMenu());//GEN-LINE:|3-startMIDlet|1|3-postAction
        // write post-action user code here
   }//GEN-BEGIN:|3-startMIDlet|2|
   //</editor-fold>//GEN-END:|3-startMIDlet|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Method: resumeMIDlet ">//GEN-BEGIN:|4-resumeMIDlet|0|4-preAction
   /**
    * Performs an action assigned to the Mobile Device - MIDlet Resumed point.
    */
   public void resumeMIDlet() {//GEN-END:|4-resumeMIDlet|0|4-preAction
        // write pre-action user code here
//GEN-LINE:|4-resumeMIDlet|1|4-postAction
        // write post-action user code here
   }//GEN-BEGIN:|4-resumeMIDlet|2|
   //</editor-fold>//GEN-END:|4-resumeMIDlet|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Method: switchDisplayable ">//GEN-BEGIN:|5-switchDisplayable|0|5-preSwitch
   /**
    * Switches a current displayable in a display. The <code>display</code> instance is taken from <code>getDisplay</code> method. This method is used by all actions in the design for switching displayable.
    * @param alert the Alert which is temporarily set to the display; if <code>null</code>, then <code>nextDisplayable</code> is set immediately
    * @param nextDisplayable the Displayable to be set
    */
   public void switchDisplayable(Alert alert, Displayable nextDisplayable) {//GEN-END:|5-switchDisplayable|0|5-preSwitch
        // write pre-switch user code here
       Display display = getDisplay();//GEN-BEGIN:|5-switchDisplayable|1|5-postSwitch
       if (alert == null) {
           display.setCurrent(nextDisplayable);
       } else {
           display.setCurrent(alert, nextDisplayable);
       }//GEN-END:|5-switchDisplayable|1|5-postSwitch
        // write post-switch user code here
   }//GEN-BEGIN:|5-switchDisplayable|2|
   //</editor-fold>//GEN-END:|5-switchDisplayable|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Method: commandAction for Displayables ">//GEN-BEGIN:|7-commandAction|0|7-preCommandAction
   /**
    * Called by a system to indicated that a command has been invoked on a particular displayable.
    * @param command the Command that was invoked
    * @param displayable the Displayable where the command was invoked
    */
   public void commandAction(Command command, Displayable displayable) {//GEN-END:|7-commandAction|0|7-preCommandAction
        // Insert global pre-action code here
       if (displayable == formHelp) {//GEN-BEGIN:|7-commandAction|1|34-preAction
           if (command == backCommand) {//GEN-END:|7-commandAction|1|34-preAction
                // Insert pre-action code here
               switchDisplayable(null, getListMenu());//GEN-LINE:|7-commandAction|2|34-postAction
                // Insert post-action code here
           }//GEN-BEGIN:|7-commandAction|3|20-preAction
       } else if (displayable == formPlayerName) {
           if (command == cancelCommand) {//GEN-END:|7-commandAction|3|20-preAction
                // Insert pre-action code here
               switchDisplayable(null, getListMenu());//GEN-LINE:|7-commandAction|4|20-postAction
                // Insert post-action code here
           } else if (command == okCommand) {//GEN-LINE:|7-commandAction|5|23-preAction
                strItemCurrentPlayerName.setText(txtPlayerName.getString()); //update the name in formPlayerName
                puyoConfig.setCurrentPlayerName(txtPlayerName.getString()); //update the name in PuyoConfig 
                switchDisplayable(null, getListMenu());//GEN-LINE:|7-commandAction|6|23-postAction
                // Insert post-action code here
           }//GEN-BEGIN:|7-commandAction|7|15-preAction
       } else if (displayable == listMenu) {
           if (command == List.SELECT_COMMAND) {//GEN-END:|7-commandAction|7|15-preAction
                // write pre-action user code here
               listMenuAction();//GEN-LINE:|7-commandAction|8|15-postAction
                // write post-action user code here
           }//GEN-BEGIN:|7-commandAction|9|7-postCommandAction
       }//GEN-END:|7-commandAction|9|7-postCommandAction
        else if(displayable == puyoWindow){
             if (command == exitCommand) { 
                 boolean bIsScoreInserted = puyoWindow.notifyScoreObserver();  //notify the score observer(in this case, the class itself)
                                                     //to update the high score record if necessary     
                if(!bIsScoreInserted)
                    getDisplay().setCurrent(getListMenu()); 
            }else if(command == pauseCommand){
                puyoWindow.changePauseState();
                puyoWindow.removeCommand(pauseCommand);
                puyoWindow.addCommand(resumeCommand);
             }else if(command == resumeCommand){
                puyoWindow.changePauseState();
                puyoWindow.removeCommand(resumeCommand);
                puyoWindow.addCommand(pauseCommand);
            }
        }else if(displayable == scoreScreen){
            if (command == backCommand) { 
                getDisplay().setCurrent(getListMenu()); 
            }        
        }
   }//GEN-BEGIN:|7-commandAction|10|
   //</editor-fold>//GEN-END:|7-commandAction|10|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: listMenu ">//GEN-BEGIN:|13-getter|0|13-preInit
   /**
    * Returns an initiliazed instance of listMenu component.
    * @return the initialized component instance
    */
   public List getListMenu() {
       if (listMenu == null) {//GEN-END:|13-getter|0|13-preInit
            // Insert pre-init code here
           listMenu = new List("Puyo Puyo", Choice.IMPLICIT);//GEN-BEGIN:|13-getter|1|13-postInit
           listMenu.append("New Game", null);
           listMenu.append("Set player name", null);
           listMenu.append("Show high scores", null);
           listMenu.append("Reset high scores", null);
           listMenu.append("Help", null);
           listMenu.append("Exit game", null);
           listMenu.setCommandListener(this);
           listMenu.setSelectedFlags(new boolean[] { false, false, false, false, false, false });//GEN-END:|13-getter|1|13-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|13-getter|2|
       return listMenu;
   }
   //</editor-fold>//GEN-END:|13-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Method: listMenuAction ">//GEN-BEGIN:|13-action|0|13-preAction
   /**
    * Performs an action assigned to the selected list element in the listMenu component.
    */
   public void listMenuAction() {//GEN-END:|13-action|0|13-preAction
        // enter pre-action user code here
       switch (getListMenu().getSelectedIndex()) {//GEN-BEGIN:|13-action|1|17-preAction
           case 0://GEN-END:|13-action|1|17-preAction
                // write pre-action user code here
                ((PuyoWindow)getpuyoWindow()).Init(puyoConfig);
//GEN-LINE:|13-action|2|17-postAction
                // write post-action user code here
                switchDisplayable(null,puyoWindow);    
                break;//GEN-BEGIN:|13-action|3|18-preAction
           case 1://GEN-END:|13-action|3|18-preAction
                // write pre-action user code here
               switchDisplayable(null, getFormPlayerName());//GEN-LINE:|13-action|4|18-postAction
                // write post-action user code here
               break;//GEN-BEGIN:|13-action|5|30-preAction
           case 2://GEN-END:|13-action|5|30-preAction
                // write pre-action user code here
//GEN-LINE:|13-action|6|30-postAction
                // write post-action user code here
                switchDisplayable(null,getScoreScreen());
                break;//GEN-BEGIN:|13-action|7|31-preAction
           case 3://GEN-END:|13-action|7|31-preAction
                // write pre-action user code here
//GEN-LINE:|13-action|8|31-postAction
                // write post-action user code here
                 ((ScoreScreen)getScoreScreen()).resetScores();
                 Alert alert = new Alert("Info", "Score records have been reset",null,null);
                 switchDisplayable(alert, getListMenu()); 
                 break;//GEN-BEGIN:|13-action|9|32-preAction
           case 4://GEN-END:|13-action|9|32-preAction
                // write pre-action user code here
               switchDisplayable(null, getFormHelp());//GEN-LINE:|13-action|10|32-postAction
                // write post-action user code here
               break;//GEN-BEGIN:|13-action|11|39-preAction
           case 5://GEN-END:|13-action|11|39-preAction
                // write pre-action user code here
               exitMIDlet();//GEN-LINE:|13-action|12|39-postAction
                // write post-action user code here
               break;//GEN-BEGIN:|13-action|13|13-postAction
       }//GEN-END:|13-action|13|13-postAction
        // enter post-action user code here
   }//GEN-BEGIN:|13-action|14|
   //</editor-fold>//GEN-END:|13-action|14|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: formPlayerName ">//GEN-BEGIN:|19-getter|0|19-preInit
   /**
    * Returns an initiliazed instance of formPlayerName component.
    * @return the initialized component instance
    */
   public Form getFormPlayerName() {
       if (formPlayerName == null) {//GEN-END:|19-getter|0|19-preInit
            // Insert pre-init code here
           formPlayerName = new Form("Change player name", new Item[] { strItemCurrentPlayerName, getSpacer(), getTxtPlayerName() });//GEN-BEGIN:|19-getter|1|19-postInit
           formPlayerName.addCommand(getCancelCommand());
           formPlayerName.addCommand(getOkCommand());
           formPlayerName.setCommandListener(this);//GEN-END:|19-getter|1|19-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|19-getter|2|
       return formPlayerName;
   }
   //</editor-fold>//GEN-END:|19-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: spacer ">//GEN-BEGIN:|27-getter|0|27-preInit
   /**
    * Returns an initiliazed instance of spacer component.
    * @return the initialized component instance
    */
   public Spacer getSpacer() {
       if (spacer == null) {//GEN-END:|27-getter|0|27-preInit
            // Insert pre-init code here
           spacer = new Spacer(1000, 1);//GEN-LINE:|27-getter|1|27-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|27-getter|2|
       return spacer;
   }
   //</editor-fold>//GEN-END:|27-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: txtPlayerName ">//GEN-BEGIN:|28-getter|0|28-preInit
   /**
    * Returns an initiliazed instance of txtPlayerName component.
    * @return the initialized component instance
    */
   public TextField getTxtPlayerName() {
       if (txtPlayerName == null) {//GEN-END:|28-getter|0|28-preInit
            // Insert pre-init code here
           txtPlayerName = new TextField("New name", null, 12, TextField.ANY);//GEN-LINE:|28-getter|1|28-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|28-getter|2|
       return txtPlayerName;
   }
   //</editor-fold>//GEN-END:|28-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: formHelp ">//GEN-BEGIN:|33-getter|0|33-preInit
   /**
    * Returns an initiliazed instance of formHelp component.
    * @return the initialized component instance
    */
   public Form getFormHelp() {
       if (formHelp == null) {//GEN-END:|33-getter|0|33-preInit
            // Insert pre-init code here
           formHelp = new Form("Help", new Item[] { getStrItemHelp() });//GEN-BEGIN:|33-getter|1|33-postInit
           formHelp.addCommand(getBackCommand());
           formHelp.setCommandListener(this);//GEN-END:|33-getter|1|33-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|33-getter|2|
       return formHelp;
   }
   //</editor-fold>//GEN-END:|33-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: strItemHelp ">//GEN-BEGIN:|37-getter|0|37-preInit
   /**
    * Returns an initiliazed instance of strItemHelp component.
    * @return the initialized component instance
    */
   public StringItem getStrItemHelp() {
       if (strItemHelp == null) {//GEN-END:|37-getter|0|37-preInit
            // Insert pre-init code here
           strItemHelp = new StringItem("", "Speed up:   * \nSpeed down:   #\nvolume down:  1\nvolume up:  3\nMove:  left/right or 4/6\nRotate:  up/down or 2/8\n");//GEN-LINE:|37-getter|1|37-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|37-getter|2|
       return strItemHelp;
   }
   //</editor-fold>//GEN-END:|37-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: cancelCommand ">//GEN-BEGIN:|21-getter|0|21-preInit
   /**
    * Returns an initiliazed instance of cancelCommand component.
    * @return the initialized component instance
    */
   public Command getCancelCommand() {
       if (cancelCommand == null) {//GEN-END:|21-getter|0|21-preInit
            // Insert pre-init code here
           cancelCommand = new Command("Cancel", Command.CANCEL, 1);//GEN-LINE:|21-getter|1|21-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|21-getter|2|
       return cancelCommand;
   }
   //</editor-fold>//GEN-END:|21-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: okCommand ">//GEN-BEGIN:|24-getter|0|24-preInit
   /**
    * Returns an initiliazed instance of okCommand component.
    * @return the initialized component instance
    */
   public Command getOkCommand() {
       if (okCommand == null) {//GEN-END:|24-getter|0|24-preInit
            // Insert pre-init code here
           okCommand = new Command("Ok", Command.OK, 1);//GEN-LINE:|24-getter|1|24-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|24-getter|2|
       return okCommand;
   }
   //</editor-fold>//GEN-END:|24-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: backCommand ">//GEN-BEGIN:|35-getter|0|35-preInit
   /**
    * Returns an initiliazed instance of backCommand component.
    * @return the initialized component instance
    */
   public Command getBackCommand() {
       if (backCommand == null) {//GEN-END:|35-getter|0|35-preInit
            // Insert pre-init code here
           backCommand = new Command("Back", Command.BACK, 1);//GEN-LINE:|35-getter|1|35-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|35-getter|2|
       return backCommand;
   }
   //</editor-fold>//GEN-END:|35-getter|2|

   //<editor-fold defaultstate="collapsed" desc=" Generated Getter: exitCommand ">//GEN-BEGIN:|42-getter|0|42-preInit
   /**
    * Returns an initiliazed instance of exitCommand component.
    * @return the initialized component instance
    */
   public Command getExitCommand() {
       if (exitCommand == null) {//GEN-END:|42-getter|0|42-preInit
            // Insert pre-init code here
           exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:|42-getter|1|42-postInit
            // Insert post-init code here
       }//GEN-BEGIN:|42-getter|2|
       return exitCommand;
   }
   //</editor-fold>//GEN-END:|42-getter|2|

    
    /** This method returns instance for PuyoWindow, the game canvas.
     * @return Instance for PuyoWindow
     */
    public Canvas getpuyoWindow() {
        if (puyoWindow == null) {
            // Insert pre-init code here
            puyoWindow = new PuyoWindow();
            puyoWindow.addCommand(pauseCommand);
            puyoWindow.addCommand(getExitCommand());
            puyoWindow.setCommandListener(this);
            puyoWindow.registerObserver(this); //register the high score listener         
            // Insert post-init code here
        }
        return puyoWindow;
    }
    
    /** This method returns instance for PuyoWindow, the game canvas.
     * @return Instance for PuyoWindow
     */
    public Canvas getScoreScreen() {
        if (scoreScreen == null) {            
            scoreScreen = new ScoreScreen();
            scoreScreen.addCommand(getBackCommand());
            scoreScreen.setCommandListener(this);  //set the command handler           
        }
        return scoreScreen;
    }
 
    /**
     * This method should return an instance of the display.
     */

    /**
     * Returns a display instance.
     * @return the display instance.
     */
    public Display getDisplay () {
         return Display.getDisplay(this);
    }

    
    /**
     * This method should exit the midlet.
     */

    /**
     * Exits MIDlet.
     */
    public void exitMIDlet() {
        puyoConfig.write();
        switchDisplayable (null, null);
        destroyApp(true);
        notifyDestroyed();
    }
    
    /** Creates a new instance of PuyoMidlet */
    public PuyoMIDlet() {
    } 

    
    public boolean notifyScore(int score, byte level){
        if(scoreScreen.insertHighscore(strItemCurrentPlayerName.getText(),score,level)){
            Alert alert = new Alert("Congratulations!",
                                     "You've made into the top " + String.valueOf(Scores.MAX_SCORE_ENTRIES),
                                     null,null);
            alert.setTimeout(Alert.FOREVER);
            getDisplay().setCurrent(alert, scoreScreen);            
            return true;
        }
        return false;
    }

// HINT - Uncomment for accessing new MIDlet Started/Resumed logic.
// NOTE - Be aware of resolving conflicts of following methods.
    /**
     * Called when MIDlet is started.
     * Checks whether the MIDlet have been already started and initialize/starts or resumes the MIDlet.
     */
   public void startApp() {
        if (midletPaused) {
           resumeMIDlet ();
        } else {
           initialize ();
           startMIDlet ();
       }
        midletPaused = false;
   }

    /**
     * Called when MIDlet is paused.
     */
    public void pauseApp() {
        midletPaused = true;
        if (puyoWindow != null) {
            puyoWindow.pauseSound();
        }
    }

    /**
     * Called to signal the MIDlet to terminate.
     * @param unconditional if true, then the MIDlet has to be unconditionally terminated and all resources has to be released.
     */
    public void destroyApp(boolean unconditional) {
        if (puyoWindow != null) {
            puyoWindow.closeSound();
        }
    }

}
